﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;

namespace OpenSearch
{
    public enum OsdxFormat
    {
        [XmlEnum(Name = "application/rss+xml")]
        RSS = 0,
        [XmlEnum(Name = "application/atom+xml")]
        ATOM = 1,
        [XmlEnum(Name = "text/html")]
        HTML = 2
    }

    
    public class OsdxTemplate
    {
        [XmlAttribute(AttributeName = "type")]
        public OsdxFormat Format {get;set;}

        [XmlAttribute(AttributeName="template")]
        public string TemplateUrl {get;set;}
    }

    // <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:ms-ose="http://schemas.microsoft.com/opensearchext/2009/">
    [XmlRoot(Namespace = "http://a9.com/-/spec/opensearch/1.1/")]
    public class OpenSearchDescription
    {
        static string bingUrl = "http://www.bing.com/search?q=site%3A{0}+{{searchTerms}}&format=rss";

        public static OpenSearchDescription FromGenericSiteUrl(string url)
        {
            if (url.ToLower().StartsWith("http://") || url.ToLower().StartsWith("https://"))
            {
                Uri u = new Uri(url);

                OpenSearchDescription osdx = new OpenSearchDescription();
                osdx.ShortName = u.Host;
                osdx.Description = string.Format("Federated search provider for {0} provided by Bing.com", u.Host);
                osdx.Templates.Add(new OsdxTemplate { Format = OsdxFormat.RSS, TemplateUrl = string.Format(bingUrl, url) });
                return osdx;
            }
            else throw new ArgumentException("URL must include http/https protocol identifier");
        }

        public OpenSearchDescription()
        {
            Templates = new List<OsdxTemplate>();
        }

        // <ShortName>{0}</ShortName>
        public string ShortName
        {
            get;
            set;
        }

        // <Description>{0}</Description>
        public string Description
        {
            get;
            set;
        }

        // <Url format="application/rss+xml" template="http://example.com/rss.php?query={searchTerms}&amp;start={startIndex}&amp;cnt={count}" />
        [XmlElement(ElementName="Url")]
        public List<OsdxTemplate> Templates
        {
            get;
            set;
        }

        //<ms-ose:MaximumResultCount>200</ms-ose:MaximumResultCount>
        [XmlElement(Namespace = "http://schemas.microsoft.com/opensearchext/2009/")]
        public int MaximumSearchResult
        {
            get;
            set;
        }

        public string Contact
        {
            get;
            set;
        }

        public string Tags
        {
            get;
            set;
        }

        public string SerializeToXml()
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Encoding = Encoding.UTF8;
                settings.Indent = true;

                XmlWriter writer = XmlWriter.Create(xmlTextWriter, settings);

                XmlSerializer ser = new XmlSerializer(this.GetType());
                ser.Serialize(writer, this);

                MemoryStream ms = (MemoryStream)xmlTextWriter.BaseStream;
                return UTF8ByteArrayToString(ms.ToArray());
            }
        }

        private String UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            String constructedString = encoding.GetString(characters);
            return (constructedString);
        }

    }
}
/* Template options
 * {searchTerms}
    Replaced with the search terms the user types in the Windows Explorer search input box

 * {startIndex}
    Used when getting results in "pages"
    Replaced with the index for the first result item to return

 * {startPage}
    Used when getting results in "pages"
    Replaced with the page number of the set of search results to return

 * {count}
    Used when getting results in "pages"
    Replaced with the number of search results per page that Windows Explorer requests

 * {language}
    Replaced with a string that indicates the language of the query being sent

 * {inputEncoding}
    Replaced with a string (such "UTF-16") that indicates the character encoding of the query being sent

 * {outputEncoding}
    Replaced with a string (such as "UTF-16") that indicates the desired character encoding for the response from the Web service
*/